﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Jamhee.Noctiluca.Common;
using Jamhee.Noctiluca.WebServer;

namespace Jamhee.Noctiluca
{
    class WebListener
    {
        private Thread _listenThread;
        private HttpListener _httpListener;
        private IWebConfiguration _webConfig;

        private const string LOCALHOST = "localhost";
        private const string LOCALHOST_IP = "127.0.0.1";
        private const string HTTP = "http://";

        public void Start(int port, string webConfigName)
        {
            // Get http listener prefixes
            string[] prefixes = GetLocalhostPrefixes(port);

            // Load web config
            _webConfig = WebConfiguration.GetWebConfiguration(webConfigName);
            if (_webConfig == null)
            {
                return;
            }

            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");

            // Create a listener.
            _httpListener = new HttpListener();

            // Add the prefixes.
            foreach (string s in prefixes)
            {
                _httpListener.Prefixes.Add(s);
            }

            _httpListener.Start();
            _listenThread = new Thread(new ThreadStart(StartListen));
            _listenThread.Start();
        }

        private void StartListen()
        {
            HttpListenerContext context;
            IWebResponser webResponser = _webConfig.GetWebResponser();

            if (webResponser == null)
            {
                LogUtil.PrintError("Cannot get corresponding Web Responser for web config [" + _webConfig.ConfigurationFileName + "]");
                return;
            }

            while (true)
            {
                Thread.Sleep(100);

                // Note: The GetContext method blocks while waiting for a request.
                context = _httpListener.GetContext();

                if (context != null)
                {
                    webResponser.SendResponse(context, _webConfig);
                }
            }
        }

        private string[] GetLocalhostPrefixes(int port)
        {
            // Get all IP addresses
            string strHostName = Dns.GetHostName();
            IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);

            string prefixes = string.Empty;

            // Add normal IP address into array
            foreach (System.Net.IPAddress ip in ipEntry.AddressList)
            {
                // URI prefixes are required,for example "http://contoso.com:8080/index/".
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    // End with semicolon
                    prefixes += HTTP + ip + ":" + port + "/;";
                }
            }

            // Add "localhost", "127.0.0.1" and host name. End with semicolon
            prefixes += HTTP + LOCALHOST_IP + ":" + port + "/;";
            prefixes += HTTP + LOCALHOST + ":" + port + "/;";
            prefixes += HTTP + strHostName + ":" + port + "/";

            // Split it into an array by semicolon
            return prefixes.Split(';');
        }

        
    }
}
